﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StreamExtension.cs" company="">
//   
// </copyright>
// <summary>
//   The stream extension.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.Core
{
    using System;
    using System.IO;

    /// <summary>
    ///   The stream extension.
    /// </summary>
    public static class StreamExtension
    {
        #region Public Methods and Operators

        /// <summary>
        /// The copy chunk to.
        /// </summary>
        /// <param name="sourceStream">
        /// The source stream. 
        /// </param>
        /// <param name="destinationStream">
        /// The destination stream. 
        /// </param>
        /// <param name="chunkSize">
        /// The chunk size. 
        /// </param>
        /// <param name="bufferSize">
        /// The buffer size. 
        /// </param>
        public static void CopyChunkTo(
            this Stream sourceStream, Stream destinationStream, int chunkSize, int bufferSize = 1024)
        {
            if (chunkSize < bufferSize)
            {
                bufferSize = chunkSize;
            }

            var buffer = new byte[bufferSize];
            var readedSize = bufferSize;
            while (chunkSize > 0 && readedSize > 0)
            {
                if (chunkSize < bufferSize)
                {
                    bufferSize = (UInt16)chunkSize;
                }

                readedSize = (UInt16)sourceStream.Read(buffer, 0, bufferSize);
                destinationStream.Write(buffer, 0, readedSize);
                chunkSize -= readedSize;
            }
        }

        /// <summary>
        /// The copy chunk to array.
        /// </summary>
        /// <param name="stream">
        /// The stream. 
        /// </param>
        /// <param name="chunkSize">
        /// The chunk size. 
        /// </param>
        /// <param name="bufferSize">
        /// The buffer size. 
        /// </param>
        /// <returns>
        /// The <see cref="byte[]"/> . 
        /// </returns>
        public static byte[] CopyChunkToArray(this Stream stream, int chunkSize, int bufferSize = 1024)
        {
            var memoryStream = CopyChunkToMemoryStream(stream, chunkSize, bufferSize);
            return memoryStream.ToArray();
        }

        /// <summary>
        /// The copy chunk to memory stream.
        /// </summary>
        /// <param name="stream">
        /// The stream. 
        /// </param>
        /// <param name="chunkSize">
        /// The chunk size. 
        /// </param>
        /// <param name="bufferSize">
        /// The buffer size. 
        /// </param>
        /// <returns>
        /// The <see cref="MemoryStream"/> . 
        /// </returns>
        public static MemoryStream CopyChunkToMemoryStream(this Stream stream, int chunkSize, int bufferSize = 1024)
        {
            var memoryStream = new MemoryStream();
            stream.CopyChunkTo(memoryStream, chunkSize, bufferSize);
            memoryStream.Position = 0;
            return memoryStream;
        }

        /// <summary>
        /// The copy to array.
        /// </summary>
        /// <param name="stream">
        /// The stream. 
        /// </param>
        /// <param name="bufferSize">
        /// The buffer size. 
        /// </param>
        /// <returns>
        /// The <see cref="byte[]"/> . 
        /// </returns>
        public static byte[] CopyToArray(this Stream stream, int bufferSize = 1024)
        {
            var memoryStream = CopyToMemoryStream(stream, bufferSize);
            return memoryStream.ToArray();
        }

        /// <summary>
        /// The copy to memory stream.
        /// </summary>
        /// <param name="stream">
        /// The stream. 
        /// </param>
        /// <param name="bufferSize">
        /// The buffer size. 
        /// </param>
        /// <returns>
        /// The <see cref="MemoryStream"/> . 
        /// </returns>
        public static MemoryStream CopyToMemoryStream(this Stream stream, int bufferSize = 1024)
        {
            var memoryStream = new MemoryStream();
            stream.CopyTo(memoryStream, bufferSize);
            memoryStream.Position = 0;
            return memoryStream;
        }

        #endregion
    }
}